home *** CD-ROM | disk | FTP | other *** search
- unit TFind;
-
- interface
-
- uses Wintypes, WinProcs, SysUtils, Classes, Controls, Forms, Dialogs, FileCtrl;
-
- const
- { Attribute bits }
- TF_ReadOnly = $0001; { Include read-only files }
- TF_Hidden = $0002; { Include hidden files }
- TF_SysFile = $0004; { Include system files }
- TF_AllAttribs = $0007; { mask for attributes }
-
- { Drive Flags - only apply if no drive letter given }
- TF_DefDrive = $0008; { search default drive }
- TF_Removable = $0010; { search removable drives }
- TF_Fixed = $0020; { search fixed drives }
- TF_Remote = $0040; { search networked drives }
- TF_CDROM = $0080; { search CDROM drives }
- TF_RamDisk = $0100; { search RAM disks }
- TF_AllDrives = $01f8; { mask for drive flags }
-
- { Misc flags }
- TF_ZIPOnly = $4000; { ONLY look inside ZIP files }
- TF_ZIP = $8000; { Include ZIP files in search }
-
- type
- TTreeFindProgress = procedure (Sender: TObject; const Dir: String) of object;
-
- TTreeFind = class (TObject)
- private
- flags: Word;
- fSpec: String;
- fFileSpec: String;
- fList: TStringList;
- fProgress: TTreeFindProgress;
- function BuildDriveList (DriveList: TStringList): Boolean;
- procedure TreeSearch (const Spec: String);
- procedure SearchZipFile (const ZipFileName: String; const Spec: String);
- public
- constructor Create;
- destructor Destroy; override;
- property SearchFlags: Word read flags write flags;
- property FileSpec: String read fFileSpec write fFileSpec;
- property TheList: TStringList read fList;
- property Progress: TTreeFindProgress read fProgress write fProgress;
- procedure Execute;
- end;
-
- implementation
-
- uses Match, Zip;
-
- { TTreeFind }
-
- constructor TTreeFind.Create;
- begin
- flags := TF_DefDrive;
- fSpec := '*.*';
- fList := TStringList.Create;
- end;
-
- destructor TTreeFind.Destroy;
- begin
- fList.Free;
- Inherited Destroy;
- end;
-
- function TTreeFind.BuildDriveList (DriveList: TStringList): Boolean;
- var
- Str: String;
- DType, Idx: Integer;
- DCB: TDriveComboBox;
- begin
- Result := True;
- { If no drive flags specified, time to bottle out }
- if Flags and TF_AllDrives = 0 then begin
- Result := False;
- Exit;
- end;
-
- { First, handle the simple TF_DefDrive case }
- if Flags and TF_DefDrive = TF_DefDrive then begin
- Flags := Flags and (not TF_DefDrive);
- GetDir (0, Str);
- DriveList.Add (UpperCase (Copy (Str, 1, 2)));
- end;
-
- { If other drive flags also present ...}
- if Flags <> 0 then begin
- { Create a temporary errrr...hack...to enumerate the drives! }
- DCB := TDriveComboBox.Create (Application.MainForm);
- try
- DCB.Parent := Application.MainForm;
- DCB.Visible := False;
- DCB.TextCase := tcUpperCase;
-
- { Loop through each drive in the list }
- for Idx := 0 to DCB.Items.Count - 1 do begin
- Str := Copy (DCB.Items [Idx], 1, 2);
- DType := GetDriveType (PChar (Str + '\'));
- if (DType > Drive_No_Root_Dir) { Valid drive } and
- (Flags and (1 shl (DType + 2)) <> 0) then
- DriveList.Add (Str);
- end;
- finally
- DCB.Free;
- end;
- end;
- end;
-
- procedure TTreeFind.SearchZipFile (const ZipFileName: String; const Spec: String);
- var
- idx: Integer;
- zp: TZipFile;
- fName: String;
- begin
- zp := TZipFile.Create (ZipFileName);
- try
- for idx := 0 to zp.FilesCount - 1 do
- begin
- fName := ExtractFileName (zp.FileName [idx]);
- if IsMatch (Copy (Spec, 3, 255), fName) then
- fList.Add (fName + #9 + ZipFileName);
- end;
- finally
- zp.Free;
- end;
- end;
-
- procedure TTreeFind.TreeSearch (const Spec: String);
- var
- Dir: String;
- Err: Integer;
- SearchRec: TSearchRec;
- begin
- try
- { Find first matching file }
- Err := FindFirst ('*.*', Flags and TF_AllAttribs, SearchRec);
- GetDir (0, Dir);
- if Dir [Length (Dir)] <> '\' then Dir := Dir + '\';
-
- if Assigned (fProgress) and (Flags and TF_ZipOnly = 0) then fProgress (Self, Dir);
-
- { Loop for all files which match the specification }
- while Err = 0 do begin
- if Flags and TF_ZipOnly = 0 then
- if IsMatch (Copy (Spec, 3, 255), SearchRec.Name) then fList.Add (Dir + SearchRec.Name);
-
- { If it doesn't match the spec, it might still be a ZIP file ! }
- if (Flags and (TF_ZIP or TF_ZIPOnly) <> 0) and IsMatch ('*.ZIP', SearchRec.Name) then
- begin
- { Time to do some ZIP parsing ! }
- fProgress (Self, Dir + SearchRec.Name);
- SearchZipFile (Dir + SearchRec.Name, Spec);
- end;
-
- Err := FindNext (SearchRec);
- end;
- FindClose (SearchRec);
-
- { Find first sub-directory (if any) }
- Err := FindFirst ('*.*', (Flags and TF_AllAttribs) or faDirectory, SearchRec);
-
- { Loop for all sub-directories in this directory }
- while Err = 0 do begin
- if ((SearchRec.Attr and faDirectory = faDirectory) and (SearchRec.Name [1] <> '.')) then
- begin
- ChDir (SearchRec.Name);
- TreeSearch (Spec);
- ChDir('..');
- end;
- Err := FindNext (SearchRec);
- end;
- FindClose (SearchRec);
- except
- { Should probably handle List-full errors here, but this }
- { isn't likely to be an issue for 32-bit Delphi. }
- end;
- end;
-
- procedure TTreeFind.Execute;
- var
- Idx: Integer;
- DirStash: String;
- DriveList: TStringList;
- begin
- fList.Clear;
- { If no FSpec supplied, then use *.* }
- fSpec := fFileSpec;
- if fSpec = '' then fSpec := '*.*';
-
- DriveList := TStringList.Create;
- try
- DriveList.Sorted := True;
- { If drive letter specified, only one drive to check }
- if fSpec [2] = ':' then begin
- DriveList.Add (UpperCase (Copy (fSpec, 1, 2)));
- Delete (fSpec, 1, 2);
- end
- { Enumerate drives }
- else if not BuildDriveList (DriveList) then Exit;
-
- Screen.Cursor := crHourglass;
- try
- { Now apply TreeSearch to each drive }
- for Idx := 0 to DriveList.Count - 1 do
- begin
- { Save current directory for the drive }
- GetDir (Ord (DriveList [Idx][1]) - $40, DirStash);
- { Start from root }
- ChDir (DriveList [Idx] + '\');
- { Do the search }
- TreeSearch (DriveList [Idx] + FSpec);
- { Restore stashed directory }
- ChDir (DirStash);
- end;
- finally
- Screen.Cursor := crDefault;
- end;
- finally
- DriveList.Free;
- end;
- end;
-
- end.
-